/**
 * futures : masterlink.futures.dao.HibernateBaseDao.java
 */
package masterlink.futures.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;

import baytony.util.Assert;
import baytony.util.Util;

/**
 * TODO Write the description
 *
 * @author : tonyyang
 * Create date : 2011/10/25
 * @version 1.0.0	
 */
public abstract class SpringHibernateDao<Bean extends Serializable, ID extends Serializable> extends SpringTemplateDao implements Dao<Bean, ID> {
	
	private Class<Bean> persistentBean;
	
	@SuppressWarnings("unchecked")
	public SpringHibernateDao(){
		persistentBean=(Class<Bean>) ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	@Override
	public void save(Bean bean) {
		Assert.notNull(bean,"The given bean can not be null");
		long start=System.currentTimeMillis();
		try{
			log.trace("Begin save bean {} ",bean);
			getTemplate().save(bean);
		}catch (RuntimeException e) {
			log.error("Error happen while saving bean {}",bean,e);
			throw e;
		}finally{
			log.info("Save bean {} execute time {} ms",bean,(System.currentTimeMillis()-start));
		}
	}
	
	@Override
	public void save(List<Bean> list) {
		if(!Util.isEmptyList(list)){
			for(Bean b:list){
				save(b);
			}
		}
	}
	
	@Override
	public void update(Bean bean) {
		Assert.notNull(bean,"The given bean can not be null");
		long start=System.currentTimeMillis();
		try{
			log.trace("Begin update bean {} ",bean);
			getTemplate().update(bean);
		}catch (RuntimeException e) {
			log.error("Error happen while updating bean {}",bean,e);
			throw e;
		}finally{
			log.info("Update bean {} execute time {} ms",bean,(System.currentTimeMillis()-start));
		}
	};
	
	@Override
	public void update(List<Bean> list) {
		if(!Util.isEmptyList(list)){
			for(Bean b:list){
				update(b);
			}
		}
	}
	
	@Override
	public void delete(Bean bean) {
		Assert.notNull(bean,"The given bean can not be null");
		long start=System.currentTimeMillis();
		try{
			log.trace("Begin delete bean {} ",bean);
			getTemplate().delete(bean);
		}catch (RuntimeException e) {
			log.error("Error happen while deleting bean {}",bean,e);
			throw e;
		}finally{
			log.info("Delete bean {} execute time {} ms",bean,(System.currentTimeMillis()-start));
		}
	};
	
	@Override
	public void delete(List<Bean> list) {
		if(!Util.isEmptyList(list)){
			for(Bean b:list){
				delete(b);
			}
		}
	}
	
	@Override
	public Bean findById(ID id) {
		Assert.notNull(id,"The id to find by can not be null");
		long start=System.currentTimeMillis();
		Bean b=null;
		try{
			log.trace("Finding bean {} by id={}",persistentBean.getName(),id);
			b=getTemplate().get(persistentBean,id);
		}catch (RuntimeException e) {
			log.error("Error happen while find by id= {}",id,e);
			throw e;
		}finally{
			log.info("{}. Find by id {} execute time {} ms",new Object[]{(b==null?"No object was found":b),id,(System.currentTimeMillis()-start)});
		}
		return b;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<Bean> findAll() {
		long start=System.currentTimeMillis();
		List<Bean> all=null;
		try{
			log.trace("Find all Objects for bean {}",persistentBean.getName());
			all=getTemplate().execute(new HibernateCallback<List<Bean>>() {
				@Override
				public List<Bean> doInHibernate(Session session)
						throws HibernateException, SQLException {
					return session.createCriteria(persistentBean).list();
				}
			});
		}catch (RuntimeException e) {
			log.error("Error happen while find all bean {}",persistentBean.getName(),e);
			throw e;
		}finally{
			log.info("{} objects found for Find all bean {} execute time {} ms",new Object[]{all==null?0:(all.size()),persistentBean.getName(),(System.currentTimeMillis()-start)});
		}
		return all;
	}
	
}
